<?php
/**
* Copyright 2009 Waag Society <http://www.waag.org>
* This file is part of Annotrax.
*
* Annotrax is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License,
* or (at your option) any later version.
*
* Annotrax is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Annotrax.
* If not, see http://www.gnu.org/licenses/gpl.html
*/

?>
<?php
/**
 * Model for domain data
 *
 * A domain is considered a metadata with keywords; it diffentiates ambiguous keywords like
 * "bank" => domain finance or "bank" => domain furniture
 *
 * @author Matthijs van Henten  <Matthijs@waag.org>
 * @license GNU GPL 2.0
 * @verson 0.1
 * @copyright Copyright (c) 2009, Waag Society
 */
class Default_Model_Domain{
	// class constants
	const STRING_NAME_LENGTH		= 255;
	const STRING_DESCRIPTION_LENGTH = 1024;

	// data
	private $id;
	private $name;
	private $description;

	// properties
	private $mapper;

	/**
	 * Class constructor
	 *
	 * @param mixed $args If args is an array, arguments are passed to __set.
	 * 						if args is an integer, $id is set
	 *
	 * @return Default_Model_Domain $domain
	 */
	public function __construct( $args = null ){
		if( is_numeric( $args ) ){
			$this->id = (int) $args;
		}
		else if( is_array( $args ) || is_object( $args ) ){
			foreach( $args as $key => $value ){
				$this->__set( $key, $value );
			}
		}
	}


	/**
	 * Sets $name to $value, either by invoking a setter function of this class,
	 * or by setting the property directly if it exists
	 */
    public function __set( $name, $value ){
		if( property_exists( $this, $name ) ){
			if( ($method = 'set' . ucfirst( $name )) && method_exists( $this, $method ) ){
				$this->$method( $value );
			}
			else{
				$this->$name = $value;
			}
		}
    }

	/**
	 * Gets property $name for this object, either by looking for a getter function, or
	 * doing a database lookup in case the value is not set yet
	 *
	 * @param string $name The name of the property
	 * @param mixed Null or the value
	 */
    public function __get( $name){
        if( property_exists( $this, $name ) ){
			if( ($method = 'get' . ucfirst( $name )) && method_exists( $this, $method ) ){
				return $this->$method();
			}
			else if( null == $this->$name ){
				$this->find();
			}

			return $this->$name;
        }
    }

	/**
	 * Sets the name, assert the correct length
	 *
	 * @param string $name Name for the domain
	 * @return Default_Model_Domain $this Fluent interface
	 */
	public function setName( $value ){
		$this->name = substr($value, 0, self::STRING_NAME_LENGTH );
		return $this;
	}

	/**
	 * Sets the description, assert the correct length
	 *
	 * @param string $value Description for the domain
	 * @return Default_Model_Domain $this Fluent interface
	 */
	public function setDescription( $value ){
		$this->description = substr($value, 0, self::STRING_DESCRIPTION_LENGTH );
		return $this;
	}

	/**
	 * Set ID. Must be greater than Zero
	 *
	 * @param int $value Integer ID
	 * @return Defautl_Model_Domain $this Fluent interface
	 */
	public function setId( $value ){
		if( (int) $value > 0 ){
			$this->id = (int) $value;
		}
		return $this;
	}

	/**
	 * Saves this domain
	 * - update if id or name is set and found
	 * - insert if cannot be found
	 *
	 * @return Defautl_Model_Domain $this Fluent interface
	 */
	public function save(){
		$this->getMapper()->save( $this );
		return $this;
	}

	/**
	 * Fetches a list of all domains
	 *
	 * @return array Array with domain objects
	 */
	public function fetchAll(){
		return $this->getMapper()->fetchAll();
	}

	/**
	 * Populates the object if it can be found
	 * Either id or name must be set
	 */
	private function find(){
		if( isset( $this->id ) ){
			$this->getMapper()->find( $this );
		}
		else if( isset( $this->name ) ){
			$this->getMapper()->findByName( $this );
		}
		return $this;
	}

    /**
     * Fetch or instantiates the mapper
     * @return object default_model_mapper
     */
    private function getMapper(){
        if( $this->mapper === null ){
            $mapperName = get_class( $this ) . 'Mapper';
            $this->setMapper( new $mapperName() );
        }

        return $this->mapper;
    }

    /**
     * Set mapper
     * @param default_model_mapper $mapper
     */
    private function setMapper( $mapper ){
        $this->mapper = $mapper;
        return $this;
    }


}
